﻿using System;
using System.Collections.Generic;
using UnityEngine;
using Yoozoo.Framework.Core;
using Yoozoo.Gameplay.City;
using Yoozoo.Managers;

namespace Gameplay.PVE.Survivor
{
    public class GameObjectPool<T> where T:BattleGameObject
    {
        private string path;
        private int resId;
        private int poolCount;
        private List<T> unUsedPool = new List<T>();
        private List<T> totalPool = new List<T>();
        private int usingPeak = 0;
        private int usingCount = 0;
        private Transform root;
        
        public void Initialize(int resId,string path,int poolCount)
        {
            this.resId = resId;
            this.path = path;
            this.poolCount = poolCount;
            root = new GameObject().transform;
#if UNITY_EDITOR
            var paths = path.Split('/');
            root.name = paths[paths.Length - 1].Split(',')[0];
#endif
            root.transform.SetParent(BattlePoolManager.Instance.Root);
            for (int i = 0; i < poolCount; i++)
            {
                var gameObject = Construct();
                gameObject.Parent = root;
                gameObject.Position = BattleConstValue.DEFAULT_POINT;
                unUsedPool.Add(gameObject);
            }
        }

        public T Construct()
        {
            var gameObject = ClassManager.Get<T>();
            gameObject.resId = resId;
            gameObject.Create(path, null);
            totalPool.Add(gameObject);
            return gameObject;
        }

        protected virtual void OnUsed(T gameObject)
        {

        }
        
        protected virtual void OnRelease(T gameObject)
        {
            gameObject.Parent = root;
            gameObject.Position = BattleConstValue.DEFAULT_POINT;
            gameObject.OnRelease();
        }
        
        public T Get()
        {
            usingCount++;
            usingPeak = Mathf.Max(usingPeak, usingCount);
            T obj = null;
            if (unUsedPool.Count > 0)
            {
                var index = unUsedPool.Count - 1;
                for (int i = index; i >= 0; i--)
                {
                    var target = unUsedPool[i];
                    if (target.IsLoading)
                    {
                        continue;
                    }
                    obj = target;
                    unUsedPool.RemoveAt(i);
                    break;
                }
            }

            if (obj == null)
            {
                obj = Construct();
            }
            OnUsed(obj);
            return obj;
        }
        
        public void Release(T gameObject)
        {
            usingCount--;
            unUsedPool.Add(gameObject);
            OnRelease(gameObject);
        }

        public void Dispose()
        {
            for (int i = 0; i < totalPool.Count; i++)
            {
                totalPool[i].Dispose();
                ClassManager.Free(totalPool[i]);
            }
            totalPool.Clear();
            unUsedPool.Clear();
            usingCount = 0;
            usingPeak = 0;
            GameObject.DestroyImmediate(root.gameObject);
        }
    }
}
